package com.hmall.search.service;

import com.alibaba.fastjson.JSON;
import com.hamll.common.client.ItemClient;
import com.hmall.common.dto.ItemDTO;
import com.hmall.common.dto.PageDTO;
import com.hmall.search.entity.ItemDoc;
import com.hmall.search.entity.RequestParams;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ItemSearchSerivce {

    @Autowired
    private RestHighLevelClient highLevelClient;
    /**
     * 导入数据
     * @param list
     */
    public void importIndex(List<ItemDTO> list) {
        BulkRequest bulkRequest = new BulkRequest();
        for (ItemDTO itemDTO : list) {
            IndexRequest indexRequest = new IndexRequest("item").id(itemDTO.getId().toString());
            ItemDoc itemDoc = new ItemDoc(itemDTO);
            indexRequest.source(JSON.toJSONString(itemDoc), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        try {
            highLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关键词搜索 match
     *
     * @param params
     * @return
     */
    public PageDTO<ItemDoc> search(RequestParams params) {

        SearchRequest searchRequest = new SearchRequest("item");
        //使用布尔查询
        BoolQueryBuilder boolQueryBuilder = baseQuery(params);
        //设置查询的条件
        searchRequest.source().query(boolQueryBuilder);
        //设置分页
        int index = (params.getPage() - 1) * params.getSize();
        searchRequest.source().from(index);
        searchRequest.source().size(params.getSize());
        //设置排序
        String sortBy = params.getSortBy();
        if (sortBy.equals("sold")) {
            //销量排序
            searchRequest.source().sort(sortBy, SortOrder.DESC);
        } else if (sortBy.equals("price")) {
            //价格排序
            searchRequest.source().sort(sortBy, SortOrder.DESC);
        }

        try {
            SearchResponse response = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = response.getHits();
            long total = hits.getTotalHits().value;
            List<ItemDoc> list = new ArrayList<>();
            for (SearchHit hit : hits) {
                String jsonStr = hit.getSourceAsString();
                ItemDoc itemDoc = JSON.parseObject(jsonStr, ItemDoc.class);
                list.add(itemDoc);
            }
            return new PageDTO<>(total, list);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private BoolQueryBuilder baseQuery(RequestParams params) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (StringUtils.isNotBlank(params.getKey())) {
            boolQuery.must(QueryBuilders.matchQuery("all", params.getKey()).operator(Operator.AND));
        } else {
            boolQuery.must(QueryBuilders.matchAllQuery());
        }
        //过滤条件也用booler去做
        if (StringUtils.isNotBlank(params.getBrand())) {
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (StringUtils.isNotBlank(params.getCategory())) {
            boolQuery.filter(QueryBuilders.termQuery("category", params.getCategory()));
        }
        Long maxPrice = params.getMaxPrice();
        Long minPrice = params.getMinPrice();
        if (minPrice != null && maxPrice != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").gt(minPrice * 100).lt(maxPrice * 100));
        }
        return boolQuery;
    }


    /**
     * 获取过滤项
     * @param params
     * @return
     */
    public Map<String, List<String>> filters(RequestParams params) {

        Map<String, List<String>> map = new HashMap<>();

        SearchRequest searchRequest = new SearchRequest("item");

        BoolQueryBuilder boolQueryBuilder = baseQuery(params);

        searchRequest.source().query(boolQueryBuilder);
        //设置聚合条件
        searchRequest.source().aggregation(
                AggregationBuilders.terms("brandAggs").field("brand").size(20)
        );
        searchRequest.source().aggregation(
                AggregationBuilders.terms("categoryAggs").field("category").size(20)
        );
        try {
            SearchResponse response = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //获取聚合结果
            Aggregations aggregations = response.getAggregations();

            Terms brandAggs = aggregations.get("brandAggs");
            List<? extends Terms.Bucket> brandAggsBuckets = brandAggs.getBuckets();
            List<String> brandList = new ArrayList<>();
            for (Terms.Bucket brandAggsBucket : brandAggsBuckets) {
                String key = brandAggsBucket.getKeyAsString();
                brandList.add(key);
            }
            Terms categoryAggs = aggregations.get("categoryAggs");
            List<String> categoryList = new ArrayList<>();
            List<? extends Terms.Bucket> categoryAggsBuckets = categoryAggs.getBuckets();
            for (Terms.Bucket categoryAggsBucket : categoryAggsBuckets) {
                String Key = categoryAggsBucket.getKeyAsString();
                categoryList.add(Key);
            }
            map.put("brand", brandList);
            map.put("category", categoryList);
            return map;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 删除索引
     * @param itemId
     */
    public void removeIndex(String itemId) {

        DeleteRequest deleteRequest = new DeleteRequest("item").id(itemId);
        try {
            highLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Autowired
    private ItemClient itemClient;
    /**
     * 创建一个索引
     * @param itemId
     */
    public void createIndex(String itemId) {

//        远程调用item
        ItemDTO itemDTO = itemClient.getById(Long.valueOf(itemId));


        IndexRequest indexRequest = new IndexRequest("item").id(itemDTO.getId().toString());
        ItemDoc itemDoc = new ItemDoc(itemDTO);
        indexRequest.source(JSON.toJSONString(itemDoc), XContentType.JSON);
        try {
            highLevelClient.index(indexRequest,RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
